<template>
  <div id="webgl"></div>
  <div class="btn">全屏</div>
</template>

<script setup lang="ts">
import { ref, onMounted } from "vue";
import * as THREE from "three";
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { GUI } from "three/addons/libs/lil-gui.module.min.js";
// 引入性能监视器stats.js
import Stats from "three/addons/libs/stats.module.js";
import { useFullscreen } from "@vueuse/core";

const { isFullscreen, enter, exit, toggle } = useFullscreen();

// 创建3D场景对象Scene
const scene = new THREE.Scene();
//创建一个长方体几何对象Geometry
const geometry = new THREE.BoxGeometry(100, 60, 20);
//创建一个材质对象Material
const material = new THREE.MeshLambertMaterial({
  //MeshBasicMaterial不受光照影响
  color: 0xff0000, //0xff0000设置材质颜色为红色
  transparent: true, //开启透明
  opacity: 0.5, //设置透明度
});
// 两个参数分别为几何体geometry、材质material
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
//设置网格模型在三维空间中的位置坐标，默认是坐标原点
mesh.position.set(0, 10, 0);
scene.add(mesh);

// 定义threejs输出画布的尺寸(单位:像素px)
const width = window.innerWidth; //宽度
const height = window.innerHeight; //高度
// 实例化一个透视投影相机对象
const camera = new THREE.OrthographicCamera(
  -100 * (width / height),
  100 * (width / height),
  100,
  -100,
  1,
  3000
);
//相机在Three.js三维坐标系中的位置
// 根据需要设置相机位置具体值
camera.position.set(100, 100, 100);
//相机观察目标指向Threejs 3D空间中某个位置
camera.lookAt(0, 0, 0); //指向mesh对应的位置

// AxesHelper：辅助观察的坐标系
const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);

const pointLight = new THREE.PointLight(0xffffff, 1.0);
pointLight.decay = 0.0;
pointLight.position.set(400, 200, 300);
scene.add(pointLight);

// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();

renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
renderer.setClearColor(0xffffff, 1);
renderer.render(scene, camera);

// 设置相机控件轨道控制器OrbitControls
const controls = new OrbitControls(camera, renderer.domElement);
// 设置带阻尼的惯性
controls.enableDamping = true;
// 设置阻尼系数
controls.dampingFactor = 0.8;
// 如果OrbitControls改变了相机参数，重新调用渲染器渲染三维场景
controls.addEventListener("change", function () {
  renderer.render(scene, camera); //执行渲染操作
}); //监听鼠标、键盘事件

//创建stats对象
const stats = new Stats();
//stats.domElement:web页面上输出计算结果,一个div元素，
document.body.appendChild(stats.domElement);

// 实例化一个gui对象
const gui = new GUI();
let folder = gui.addFolder("立方体位置").onFinishChange((value) => {
  console.log("value:", value);
});
// gui增加交互界面，用来改变obj对应属性
folder.add(mesh.position, "x").min(0).max(180).step(1).name("立方体X轴位置");
folder.add(mesh.position, "y").min(0).max(180).step(1).name("立方体Y轴位置");
folder.add(mesh.position, "z").min(0).max(180).step(1).name("立方体Z轴位置");
const obj = {
  color: 0x00ffff,
};
// .addColor()生成颜色值改变的交互界面
gui
  .addColor(obj, "color")
  .onChange(function (value) {
    mesh.material.color.set(value);
  })
  .name("立方体颜色");

gui.add(material, "wireframe").name("立方体线框模式");

// 渲染函数
function render() {
  stats.update();
  renderer.render(scene, camera); //执行渲染操作
  mesh.rotateY(0.0005); //每次绕y轴旋转0.01弧度
  requestAnimationFrame(render); //请求再次执行渲染函数render，渲染下一帧
}
render();

onMounted(() => {
  document.getElementById("webgl").appendChild(renderer.domElement);
  // 监听窗口变化
  window.addEventListener("resize", () => {
    // 设置渲染区域尺寸
    renderer.setSize(window.innerWidth, window.innerHeight);
    // 设置相机投影矩阵属性
    camera.aspect = window.innerWidth / window.innerHeight;
    // 更新相机的投影矩阵
    camera.updateProjectionMatrix();
  });
});
</script>

<style lang="scss"></style>
